using System;
using System.Linq;
using CommonBehaviors.Actions;

using Styx;
using Styx.Logic;
using Styx.Logic.Combat;
using Styx.WoWInternals.WoWObjects;
using TreeSharp;


namespace Altarboy
{
    class Shadowpriest
    {

        #region Delegates
        public delegate bool SimpleBoolReturnDelegate(object context);
        public delegate WoWUnit UnitSelectionDelegate(object context);
        #endregion

        
        // Current Player   
        public static LocalPlayer Me { get { return StyxWoW.Me; } }

        public static Composite Target()
        {
           return new PrioritySelector(                        
            
            new Decorator(ret => AltarboySettings.Instance.EnableTargeting,
                   
                new PrioritySelector(


                        //DEV - CURRENTLY THIS IS WAY TO BUGGY.
                        ////If there are raid markers use them... always
                        ////skull first.
                        //new Decorator(ret => (
                        //    AltarboySettings.Instance.PrioritizeRaidMarkerTargeting
                        //    && TargetManager.DetectHostileTargets(40).Any(unit => TargetManager.EnemyHasRaidMarker(unit, TargetManager.RaidTargetIcon.Skull))                           
                        //    ),
                        //     new TreeSharp.Action(delegate { TargetManager.DetectHostileTargets(40).First(unit => TargetManager.EnemyHasRaidMarker(unit, TargetManager.RaidTargetIcon.Skull)).Target(); })
                        //),

                        //////x second.
                        //new Decorator(ret => (
                        //    AltarboySettings.Instance.PrioritizeRaidMarkerTargeting
                        //    && TargetManager.DetectHostileTargets(40).Any(unit => TargetManager.EnemyHasRaidMarker(unit, TargetManager.RaidTargetIcon.Cross ))),
                        //     new TreeSharp.Action(delegate { TargetManager.DetectHostileTargets(40).First(unit => TargetManager.EnemyHasRaidMarker(unit, TargetManager.RaidTargetIcon.Cross )).Target(); })
                        //),
                    
                        //This is where encounter ased logic could fit in.

                        
                        //We should have a high priority target list
                        //TODO - this needs some work.
                        new Decorator(ret =>
                            TargetManager.DetectHostileTargets(40).Any(unit => AltarboyHashes.IsSpecialMobType(unit, AltarboyHashes.MobTypes.Focus)                              
                             ),
                               new TreeSharp.Action(delegate
                               {
                                   //target the mob with the lowest health. 
                                   TargetManager.DetectHostileTargets(40).OrderBy(unit => unit.CurrentHealth).First(unit => AltarboyHashes.IsSpecialMobType(unit, AltarboyHashes.MobTypes.Focus)).Target();
                               })
                        ),
                       
                        //We have a raf leader...
                        new Decorator(ret => RaFHelper.Leader != null && RaFHelper.Leader.Combat && AltarboySettings.Instance.RaFLeaderTargeting ,
                               new PrioritySelector(

                                   //If there are any targets below 25% health and settings and cooldowns permit. Cast SWD.
                                   new Decorator (
                                     ret =>AltarboySettings.Instance.ShadowWordDeathForExecute &&
                                           !SpellManager.Spells["Shadow Word: Death"].Cooldown &&
                                           TargetManager.DetectHostileTargets(40).Any(unit => unit.HealthPercent <= 25) &&
                                           SafeToShadowWordDeath(),

                                         new TreeSharp.Action(delegate {  TargetManager.DetectHostileTargets(40).First(unit => unit.HealthPercent <= 25).Target(); })                                       
                                   ),

                                   //We should AOE (Mind Sear) - And use the RafLeader as the target.
                                   new Decorator(ret => AltarboySettings.Instance.UseMindSear &&
                                                        AltarboySettings.Instance.EnableMindSearTargeting &&
                                                        !Me.IsMoving &&
                                                        TargetManager.NumOfHostileWithinRange(RaFHelper.Leader, 10) >= AltarboySettings.Instance.MindSearHostileCount &&
                                                        RaFHelper.Leader.Distance2D <= 35,
                                           
                                           //the action below should be wrapped in a priority selector.
                                           //even though there are enough mobs to justify using mind sear
                                           //we might need to trigger es / use swd / user shadow fiend

                                           new TreeSharp.Action(delegate { RaFHelper.Leader.Target(); })
                                    ),

                                    //We should MultiDot 
                                    new Decorator(
                                        ret => (
                                            //lets keep the range to within 25 yards of the tank so its possible for them to keep some kinda aggro.
                                            AltarboySettings.Instance.EnableMultiDotTargeting  &&
                                            TargetManager.NumOfHostileWithinRange(RaFHelper.Leader, 35) > 1 
                                       ),
                                       new PrioritySelector(
                                          
                                           //Dot the tank target first
                                           new Decorator(ret=>
                                              TargetNeedsMultiDot(RaFHelper.Leader.CurrentTarget) ,
                                              new TreeSharp.Action(delegate { RaFHelper.Leader.CurrentTarget.Target(); })  
                                          ),

                                          //Dot any other targets next
                                          new Decorator(ret=> 
                                              TargetManager.DetectHostileTargets(35).Any(TargetNeedsMultiDot),
                                              new TreeSharp.Action(delegate { TargetManager.DetectHostileTargets(35).First(TargetNeedsMultiDot).Target(); })  
                                          )                                         
                                          
                                       )
                                    
                                    ),

                                    //Todo - Need to add some cc checks, threat checks, some range checks, some is dead checks, etc

                                   // Just use the leader's target if it's in range.
                                   new Decorator(ret => (
                                            RaFHelper.Leader.CurrentTarget != null && 
                                            TargetManager.IsUnitInRange(RaFHelper.Leader.CurrentTarget, 40)),
                                        new TreeSharp.Action(delegate { RaFHelper.Leader.CurrentTarget.Target(); })
                                   )

                                   // Use anything that is attacking the leader in range


                               )
                           ),
                           
                           //Solo targeting logic goes here.

                          new ActionAlwaysSucceed()

                      )

               ),

                 new ActionAlwaysSucceed()

            );
        }

        public static Composite Pull()
        {

          return  AltarboyComposites.CastSpell("Devouring Plague", ret => true, Me.CurrentTarget);
             
        }
             
        public static Composite Attack() {
            return new Sequence(
              
                //Select a target
                Target(),

                //Then kill it.
                new Decorator(
                  ret => !CastManager.IsHymning() || Me.IsFalling , //Added falling clause cause was killing me on Ragnaros.
                   new PrioritySelector(
                          MindSearDps(ret => ShouldMindSear() &&  AuraManager.GetAuraTimeLeft("Mind Sear", Me.CurrentTarget, true).TotalSeconds <= AltarboySettings.Instance.ClippingDuration
                       ),
                       SingleTargetDps()
                   )             
                )           
                    
            );
                    
        }
              

       #region CoolDowns

        private static Composite UseCoolDowns()
        {
            return new PrioritySelector(
              
                //Volcanic Potion during Bloodlust (will move this out when I can)
                AltarboyComposites.UseItemById(58091, ret => (
                    CastManager.CanUseItem(58091) &&
                    AuraManager.IsLusting(Me))
                ), 

                AltarboyComposites.UseSlottedItem(
                        ret => AltarboySettings.Instance.Trinket1UseOnCD || (AltarboySettings.Instance.Trinket1UseWithArchangel && AuraManager.HasMyAura("Dark Archangel",Me)),
                     StyxWoW.Me.Inventory.Equipped.Trinket1
                ),
                 AltarboyComposites.UseSlottedItem(
                        ret => AltarboySettings.Instance.Trinket2UseOnCD || (AltarboySettings.Instance.Trinket2UseWithArchangel && AuraManager.HasMyAura("Dark Archangel", Me)),
                     StyxWoW.Me.Inventory.Equipped.Trinket2
                ),

                 AltarboyComposites.UseSlottedItem(
                        ret => AltarboySettings.Instance.EngUseBelt,
                         StyxWoW.Me.Inventory.Equipped.Waist 
                ),
               
                 AltarboyComposites.UseSlottedItem(
                        ret => AltarboySettings.Instance.EngUseGloves ||  (AltarboySettings.Instance.EngUseGlovesWithArchangel && AuraManager.HasMyAura("Dark Archangel", Me)),
                         StyxWoW.Me.Inventory.Equipped.Hands 
                )
              

            );
        }
        #endregion

       #region DPS Composites

       private static Composite SingleTargetDps()
        {
           //Never Attack Anything That we shouldnt
           return new Decorator(
               ret => TargetManager.ShouldAttack( Me.CurrentTarget),
                    new PrioritySelector(
                      UseCoolDowns(), //cant seem to detect if a trinket can but used or not... gonna have to use user settings.
                      new Decorator (ret => AuraManager.HasAuraStacks("Molten Feather", 2, Me), NormalDpsRotation(ret=> true)), // Alysrazor
                      new Decorator(ret => Me.IsMoving , MovementDps() ),
                      new Decorator(ret => IsMindSpikeTarget(), MindSpikeRotation()),
                      new Decorator(ret => !IsMindSpikeTarget(), NormalDpsRotation(ret => true))
                     )
               );
         }

       private static Composite MovementDps() {
           return new PrioritySelector(                  
               
                //Use dispersion when low on mana.
                AltarboyComposites.CastSpell("Dispersion", ret => (Me.ManaPercent <= AltarboySettings.Instance.DispersionManaPercent) , Me),

                 // I think it always makes sense to use pain first... this cans generate orbs, and apparitions.
                  AltarboyComposites.CastSpell("Shadow Word: Pain", ret => (
                      AuraManager.GetAuraTimeLeft("Shadow Word: Pain", Me.CurrentTarget, true).TotalSeconds <= .4)
                  , Me.CurrentTarget),

                   //Shadow Word Death While Moving               
                   AltarboyComposites.CastSpell("Shadow Word: Death", ret => (
                       SafeToShadowWordDeath() &&
                       AltarboySettings.Instance.ShadowWordDeathWhileMoving
                   ), Me.CurrentTarget),


                   //Shadowfiend on CD or as mana regen.
                   AltarboyComposites.CastSpell("Shadowfiend", ret => (
                       (AltarboySettings.Instance.UseShadowFiendOnCD || (AltarboySettings.Instance.UseShadowFiendForManaRegen && Me.ManaPercent <= AltarboySettings.Instance.UseShadowFiendManaPercent))                       )
                       , Me.CurrentTarget
                   ),

                   //This will spam cause its good dps...
                   AltarboyComposites.CastSpell("Devouring Plague", ret => true, Me.CurrentTarget)              

           );
       }

        private static Composite NormalDpsRotation(SimpleBoolReturnDelegate extra){

          // Altarboy.Logger.Slog(Color.Lime, "--- Single Target Max Dps Rotation  --- ");
           return new Sequence(
            
            //this is the stationary composite, so it shouldn't be an issue to face the target.
            new TreeSharp.Action(delegate {if(!Me.IsMoving){Me.CurrentTarget.Face();}}),

            new Decorator(
                ret => extra(ret),
                new PrioritySelector(

                    // This doesnt belong here but Im using it for raiding at the moment... will move later.
                    AltarboyComposites.CastSpell("Dispersion", ret => (AuraManager.HasAuraStacks("Tormented", 14, Me)), Me),


                   //Shadowfiend on Bloodlust.
                   AltarboyComposites.CastSpell("Shadowfiend", ret => (
                       AltarboySettings.Instance.ForceFiendOnBloodlust &&
                       AuraManager.IsLusting(Me)), Me.CurrentTarget
                   ),

                   //Shadow Word Death On Exectue                  
                   AltarboyComposites.CastSpell("Shadow Word: Death", ret => (
                       SafeToShadowWordDeath() &&
                       AltarboySettings.Instance.ShadowWordDeathForExecute &&
                       Me.CurrentTarget.HealthPercent <= 25
                   ), Me.CurrentTarget),


                   // I think it always makes sense to use pain first... this can generate orbs, and apparitions.
                   AltarboyComposites.CastSpell("Shadow Word: Pain", ret => (
                       AuraManager.GetAuraTimeLeft("Shadow Word: Pain", Me.CurrentTarget, true).TotalSeconds <= .4),
                      Me.CurrentTarget
                   ),


                   // If there is an orb to use, and ES is close to running out... Refresh it before applying dots.
                   AltarboyComposites.CastSpell("Mind Blast", ret =>
                       Me.IsSafelyFacing(Me.CurrentTarget) &&
                       AuraManager.HasMyAura("Shadow Orb", Me, 1) &&
                       AuraManager.GetAuraTimeLeft("Empowered Shadow", Me, true).TotalSeconds < 4,
                       Me.CurrentTarget
                   ),


                   AltarboyComposites.CastSpell("Vampiric Touch", ret => (
                       CastManager.LastSpellCast != "Vampiric Touch" &&
                       Me.IsSafelyFacing(Me.CurrentTarget) &&
                       ShouldApplyDots() &&
                       (AuraManager.GetAuraTimeLeft("Vampiric Touch", Me.CurrentTarget, true).TotalSeconds <= 2.2)
                   ), Me.CurrentTarget),


                   // DP goes second cause you can cast while moving and it does instant damage. 
                   AltarboyComposites.CastSpell("Devouring Plague", ret => (
                       ShouldApplyDots() &&
                       ShouldApplyDevouringPlague()
                   ), Me.CurrentTarget),


                   // --- Trying to delay mana regen stuff untill dots are up if possible.  ---//

                   //Use dispersion when low on mana.
                   AltarboyComposites.CastSpell("Dispersion", ret => (Me.ManaPercent <= AltarboySettings.Instance.DispersionManaPercent), Me),

                   //Shadowfiend on CD or as mana regen.
                   AltarboyComposites.CastSpell("Shadowfiend", ret => (
                       (AltarboySettings.Instance.UseShadowFiendOnCD || (AltarboySettings.Instance.UseShadowFiendForManaRegen && Me.ManaPercent <= AltarboySettings.Instance.UseShadowFiendManaPercent)) &&
                       AuraManager.GetAuraTimeLeft("Mind Flay", Me.CurrentTarget, true).TotalSeconds <= 0.5)
                       , Me.CurrentTarget
                   ),

                   //Only use Archangel when there are 5 stacks up.
               //TODO - Want to add logic to make sure this isn't cast when dots are close to needing a refresh
               // - the goal is to make sure that right after this we can maximize mindblasts and mindflays.
                   AltarboyComposites.CastSpell("Archangel", ret => (
                       AuraManager.HasMyAura("Dark Evangelism", Me, 5) &&
                       AuraManager.GetAuraTimeLeft("Vampiric Touch", Me.CurrentTarget, true).TotalSeconds > 8 &&
                       AuraManager.GetAuraTimeLeft("Mind Flay", Me.CurrentTarget, true).TotalSeconds <= 0.5)
                       , Me
                   ),

                   //Shadow Word Death For Mana                 
                   AltarboyComposites.CastSpell("Shadow Word: Death", ret => (
                       SafeToShadowWordDeath() &&
                       AltarboySettings.Instance.ShadowWordDeathForManaOnly &&
                       Me.ManaPercent <= AltarboySettings.Instance.ShadowWordDeathManaPercent
                   ), Me.CurrentTarget),


                   //Shadow Word on CD (Not sure who would want this)
                    AltarboyComposites.CastSpell("Shadow Word: Death", ret => (
                       SafeToShadowWordDeath() &&
                       AltarboySettings.Instance.ShadowWordDeathOnCD
                   ), Me.CurrentTarget),

                   //Mind blast freely if we have at least ten seconds of ES left.
                   AltarboyComposites.CastSpell("Mind Blast", ret =>
                       Me.IsSafelyFacing(Me.CurrentTarget) &&
                       AuraManager.GetAuraTimeLeft("Empowered Shadow", Me, true).TotalSeconds > 9
                       , Me.CurrentTarget
                    ),

                   //Mind blast if we have at least 1 orb up and no ES at all. (Want to get ES up as fast as possible)
                   AltarboyComposites.CastSpell("Mind Blast", ret =>
                       Me.IsSafelyFacing(Me.CurrentTarget) &&
                       AuraManager.HasMyAura("Shadow Orb", Me, 1)
                    , Me.CurrentTarget),

                   //Always use MB when you have 3 orbs
                   AltarboyComposites.CastSpell("Mind Blast",
                   ret => Me.IsSafelyFacing(Me.CurrentTarget) &&
                       (AuraManager.HasMyAura("Shadow Orb", Me, 3)
                   ), Me.CurrentTarget),


                   //Mind flay when when you have nothing else to do.. Try and clip to account for lag.
                   AltarboyComposites.CastSpell("Mind Flay", ret => (
                       Me.IsSafelyFacing(Me.CurrentTarget) &&
                       (AuraManager.GetAuraTimeLeft("Mind Flay", Me.CurrentTarget, true).TotalSeconds <= AltarboySettings.Instance.ClippingDuration)
                   ), Me.CurrentTarget)


                  //TODO - Might make sense to add some wanding logic here if you are really screwed. 
               // Low Levels might find it useful

           ))

            );
            
       }

       private static Composite MindSpikeRotation()
       {
            return new Sequence(
            //this is the stationary composite, so it shouldn't be an issue to face the target.
             new TreeSharp.Action(delegate { if (!Me.IsMoving) { Me.CurrentTarget.Face(); } }),

           //Need to add code here to respect the SWD logic specified by settings..
        
                new PrioritySelector(
                   
                    //Shadow Word Death On Exectue                  
                   AltarboyComposites.CastSpell("Shadow Word: Death", ret => (
                       SafeToShadowWordDeath() &&
                       AltarboySettings.Instance.ShadowWordDeathForExecute &&
                       Me.CurrentTarget.HealthPercent <= 25
                   ), Me.CurrentTarget),

                    AltarboyComposites.CastSpell("Mind Blast", ret => AuraManager.HasMyAura("Mind Spike", Me.CurrentTarget, 3), Me.CurrentTarget),
                    AltarboyComposites.CastSpell("Shadow Word: Death", ret => (SafeToShadowWordDeath() && AltarboySettings.Instance.ShadowWordDeathForManaOnly && Me.ManaPercent <= AltarboySettings .Instance.ShadowWordDeathManaPercent ), Me.CurrentTarget),
                    AltarboyComposites.CastSpell("Mind Spike", ret => true, Me.CurrentTarget)
               
           ));                  
       }

       private static Composite MindSearDps(SimpleBoolReturnDelegate extra)
       {
           
          //FOR NOW WE WILL ASSUME THAT WE ONLY MIND SEAR ON FRIENDLY TARGETS
          // EVENTUALLY THIS WONT BE THE CASE.
           return new Sequence(

            //this is the stationary composite, so it shouldn't be an issue to face the target.
             new TreeSharp.Action(delegate { if (!Me.IsMoving) { Me.CurrentTarget.Face(); } }),

            new Decorator(
                ret => extra(ret) ,
                new PrioritySelector(

                    // lets trigger ES first if possible
                   //  AltarboyComposites.CastSpell("Mind Blast", ret =>
                   //    Me.CurrentTarget.CurrentTarget != null &&
                   //    Me.IsSafelyFacing(Me.CurrentTarget.CurrentTarget ) &&
                   //    !Me.IsMoving &&
                   //    AuraManager.HasMyAura("Shadow Orb", Me, 1)
                   // , Me.CurrentTarget.CurrentTarget),

                   // // Mind sear is expensive... lets get some mana back.
                   //AltarboyComposites.CastSpell("Shadowfiend", ret => (
                   //      Me.CurrentTarget.CurrentTarget != null &&
                   //    (AltarboySettings.Instance.UseShadowFiendOnCD || (AltarboySettings.Instance.UseShadowFiendForManaRegen && Me.ManaPercent <= AltarboySettings.Instance.UseShadowFiendManaPercent)) &&
                   //    AuraManager.GetAuraTimeLeft("Mind Sear", Me.CurrentTarget, true).TotalSeconds <= 0.5),
                   //    Me.CurrentTarget.CurrentTarget
                   //),

                    ////Lets Execute with SWD if we can.    
                   
                    //AltarboyComposites.CastSpell("Shadow Word: Death", ret => (                          
                    //        SafeToShadowWordDeath() &&
                    //        AltarboySettings.Instance.ShadowWordDeathForExecute &&
                    //        TargetManager.DetectHostileTargets(40).Any(target => (target.HealthPercent <= 25 && target.Distance <= 35))
                    // ), TargetManager.DetectHostileTargets(40).First(target => (target.HealthPercent <= 25 && target.Distance <= 35))),
                   
                                   

                    //// lets use some SWD if possible... good time to get some mana back
                    //AltarboyComposites.CastSpell("Shadow Word: Death", ret => (
                    //                    SafeToShadowWordDeath() &&
                    //                    Me.ManaPercent <= AltarboySettings.Instance.ShadowWordDeathManaPercent &&
                    //                    AltarboySettings.Instance.ShadowWordDeathForManaOnly
                    //), false, Me.CurrentTarget.CurrentTarget),

                    AltarboyComposites.CastMindSear(ret => (AuraManager.GetAuraTimeLeft("Mind Sear", Me.CurrentTarget, true).TotalSeconds <= 0.4))
                )
               // new TreeSharp.Action(delegate { CastManager.CastSpell("Mind Sear"); })
           ));
       }
       
       #endregion

       #region Conditions

       private static Boolean SafeToShadowWordDeath() {
           if (AltarboySettings.Instance.ShadowWordDeathCheckForDebuffs) {
               if  (AuraManager.HasMyAura("Levitate", Me, 0)) { return false; }
               if (Me.HealthPercent <= 25) { return false; } // Low Health (better to be alive and not have mana)
             
               if (AuraManager.HasAuraStacks("Tormented", 0, Me)) { return false; }  //Baleroc FL Crystal Debuff (150% damage)
               if (AuraManager.HasAuraStacks("Torment", 0, Me)) { return false; }  //Baleroc FL Crystal Debuff (150% damage)              
               if (AltarboyHashes.IsSpecialMobType(Me.CurrentTarget, AltarboyHashes.MobTypes.UnsafeSWD )) { return false; }             
            
           }           
           return true;
       }

       private static Boolean ShouldApplyDots() {
           return true;
       }

       private static Boolean ShouldApplyDevouringPlague() {        
			if (TargetManager.DetectHostileTargets(200).Any(target => AuraManager.GetAuraTimeLeft("Devouring Plague", target, true).TotalSeconds >= 1.2)){
				return false;
			}			
           return true;
       }
        
       private static Boolean ShouldMindSear() {
           if (Me.IsMoving || !Me.IsSafelyFacing(Me.CurrentTarget)) { return false; }
           // Friendly target - in combat - mob count check.
           if (!AltarboySettings.Instance.UseMindSear) { return false; }

           //Make sure nothing is cced.
           if (TargetManager.CrowdControllUnitInRange(Me.CurrentTarget, 10)) return false;

           //Check targets against hash targets -dev// lets still make sure there are enough targets to justify searing in range (10yrds)
           if (AltarboyHashes.IsSpecialMobType(Me.CurrentTarget, AltarboyHashes.MobTypes.MindSear) &&
               TargetManager.NumOfHostileWithinRange(Me.CurrentTarget, 10) >= AltarboySettings.Instance.MindSearHostileCount)
           {
               return true;
           }

           if (Me.CurrentTarget.IsFriendly && Me.CurrentTarget.Combat && TargetManager.NumOfHostileWithinRange(Me.CurrentTarget, 10) >= AltarboySettings.Instance.MindSearHostileCount) { return true; }

           return false;
       }

    
        private static Boolean IsMindSpikeTarget() {
           if (Me.IsMoving || !Me.IsSafelyFacing(Me.CurrentTarget) ) { return false; }
           if (Me.CurrentTarget == null || Me.CurrentTarget.IsFriendly) { return false; }

           //Check targets against hash targets
           if (AltarboyHashes.IsSpecialMobType(Me.CurrentTarget, AltarboyHashes.MobTypes.MindSpike))
           {
                   return true;
           }
      
           if (Me.IsInRaid && ShouldMindSpikeOverDoTs() && (Me.CurrentTarget.CurrentHealth <= ((PartyManager.GroupMembers.Count * Me.MaxHealth) / 2))) { return true; }
           if ((Me.IsInParty && !Me.IsInRaid) && ShouldMindSpikeOverDoTs() && (Me.CurrentTarget.CurrentHealth <= (Me.MaxHealth - (Me.MaxHealth / 4)))) { return true; }
           if (!Me.IsInParty && Me.CurrentTarget.CurrentHealth <= (Me.MaxHealth -(Me.MaxHealth/4))) { return true; }
           return false;
       }

       // Logic to prevent ripping all DoTs off of target when casting Mind Spike.
       private static Boolean ShouldMindSpikeOverDoTs()
       {
           if (AuraManager.GetAuraTimeLeft("Devouring Plague", Me.CurrentTarget, true).TotalSeconds >= 1.5)
           {
                return false;
           }
           if (!AuraManager.HasMyAura("Vampiric Touch", Me.CurrentTarget))
           {
                return true; 
            }
           if (!AuraManager.HasMyAura("Shadow Word: Pain", Me.CurrentTarget))
           {
                return true; 
            }
            // The clauses below estimates a 1.2 second cast of Mind Spike
            return AuraManager.GetAuraTimeLeft("Shadow Word: Pain", Me.CurrentTarget, true).TotalSeconds <= 1.1;
       }

       private static Boolean TargetNeedsMultiDot(WoWUnit target)
       {
          
          if (target.Distance2D > 40) { return false; }
          return AuraManager.GetAuraTimeLeft("Vampiric Touch", target, true).TotalSeconds < 3 || AuraManager.GetAuraTimeLeft("Shadow Word: Pain", target, true).TotalSeconds < 1.5;
       }

       #endregion
     
    }
}
